package com.demomaster.quickserialport;


import android.util.Log;

import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentLinkedQueue;

import android_serialport_api.SerialPort;

public class SerialPortClient {
    private final String TAG = "SPUtilsTAG";
    public String PortPath;
    public boolean serialPortStatus = false; //是否打开串口标志
    public boolean threadStatus; //线程状态，为了安全终止线程

    public SerialPort serialPort = null;
    public InputStream inputStream = null;
    public OutputStream outputStream = null;
    public ByteUtil byteUtil = new ByteUtil();
    private ReadThread readThread;
    private SendThread sendThread;
    private ConcurrentLinkedQueue<byte[]> sendQueue;
    private boolean _sendHalt;  //下发队列临时挂起(额外增加避免干扰)

    /**
     * 打开串口
     *
     * @return serialPort串口对象
     */
    public SerialPort openSerialPort(String path, int baudrate) throws Exception {
        try {
            PortPath = path;
            serialPort = new SerialPort(new File(path), baudrate, 0);
            this.serialPortStatus = true;
            threadStatus = false;

            inputStream = serialPort.getInputStream();
            outputStream = serialPort.getOutputStream();
            //sendQueue = new ConcurrentLinkedQueue<>();
            if (readThread == null) {
                readThread = new ReadThread();
            }
            readThread.start();

            Log.i(TAG, ":Open:" + path);
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception("打开串口异常：" + e.toString());
//            Log.e(TAG, "openSerialPort: 打开串口异常：" + e.toString());
            //return serialPort;
        }
//        Log.d(TAG, "openSerialPort: 打开串口");
        return serialPort;
    }

    public void closeSerialPort() {
        try {
            if (readThread != null) {
                readThread.interrupt();
                readThread = null;
            }
            this.serialPortStatus = false;
            this.threadStatus = true; //线程状态
            inputStream.close();
            outputStream.close();
            serialPort.close();
            Log.i(TAG, ":Close:" + PortPath);
        } catch (Exception e) {
            Log.e(TAG, "Close-SocketErr:" + e.toString());
        }
    }

    public boolean send(byte[] dataArr) {
//        if(sendThread == null) {
//            sendThread = new SendThread();
//            sendThread.start();
//        }
        //boolean offered = sendQueue.offer(dataArr);
        //Log.d(TAG, "=SendQI:" + ChangeTool.ByteArrToHex(dataArr) + "[" + sendQueue.size() + "]");
        sendCore(dataArr);
        return true;
    }

    /**
     * 设定下发队列临时挂起标记，msDelay后自动解除
     *
     * @param msDelay
     */
    public void setSendHalt(int msDelay) {
        _sendHalt = true;
        new Timer().schedule(new TimerTask() {
            @Override
            public void run() {
                _sendHalt = false;
            }
        }, msDelay);
    }

    private void sendCore(byte[] dataArr) {
        if (outputStream == null) return;
        if (dataArr == null ||
                dataArr.length < 1 ||
                dataArr.length > 128)
            return;

        try {
            outputStream.write(dataArr);
            outputStream.flush();
            //忽略查询输入状态的指令
//            if (!IsMatch(dataArr, new byte[]{0x5A, (byte) 0xFF}, new byte[]{(byte) 0xA5})
//                    && !IsMatch(dataArr, new byte[]{0x01, 0x04, 0x00, 0x00, 0x00, 0x02, 0x71, (byte) 0xCB}, null))
//                Log.i(TAG, "=SendQO:" + byteUtil.ByteArrToHex(dataArr) + "[" + sendQueue.size() + "]");
        } catch (Exception e) {
            Log.e(TAG, "=Send-SocketEx:" + e.toString());
        }
    }

    private class SendThread extends Thread {
        public SendThread() {
            super("tSpSend");
        }

        @Override
        public void run() {
            super.run();
            while (true) {
                try {
                    if (!_sendHalt) {
                        byte[] bsSend = sendQueue.poll();
                        if (bsSend != null)
                            sendCore(bsSend);
                    }
                    //Thread.sleep(5);
                } catch (Exception ex) {
                    Log.e(TAG, "异常" + ex.toString());
                }
            }
        }
    }

    private class ReadThread extends Thread {
        public ReadThread() {
            super("tSpRecv");
        }

        @Override
        public void run() {
            super.run();
            while (!isInterrupted() && !threadStatus) {
                //byte[] buffer = null;
                try {
                    byte[] buffer = new byte[1024];
                    int size = inputStream.read(buffer); // 阻塞读取数据
                    if (size > 0) {
                        byte[] receivedData = Arrays.copyOf(buffer, size);
                        processData(receivedData); // 处理数据
                    }
//                    int inSize = inputStream.available();
//                    System.out.println("inSize:" + inSize);
//                    while (inSize > 0) {
//                        if (buffer == null) {
//                            buffer = new byte[inSize];
//                            inputStream.read(buffer);
//                        } else {
//                            byte[] readBuffer = new byte[inSize];
//                            inputStream.read(readBuffer);
//                            buffer = byteMerger(buffer, readBuffer);
//                        }
//                        //Thread.sleep(5);
//                        inSize = inputStream.available();
//                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }

                //if (buffer == null || buffer.length < 1) continue;
//                if(!IsMatch(buffer, new byte[] {0x2B,0x49,0x4E,0x50,0x55,0x54,0x3A},new byte[] {0x0D, 0x0A})
//                && !(buffer.length==9 && IsMatch(buffer, new byte[] {0x01,0x04,0x04},null)))
//                    Log.i(TAG, "Recv:" + ChangeTool.ByteArrToHex(buffer));

            }
        }
    }
    private void processData(byte[] data) {
        String hexStr = ByteUtil.bytesToHex(data); // 示例：字节转十六进制
        Log.d("Received", hexStr);
        if (onDataRecvListener != null) {
            onDataRecvListener.onDataReceive(PortPath, data);
        }
    }

    /**
     * 获取CRC16-Modbus校验值
     *
     * @param bytes
     * @return
     */
    public int GetCrc16(byte[] bytes, int count) {
        int CRC = 0XFFFF;
        int Polynomial = 0xA001;
        if (count < 1 || count > bytes.length)
            count = bytes.length;
        for (int i = 0; i < count; i++) {
            CRC ^= ((int) bytes[i] & 0xff);
            for (int j = 0; j < 8; j++) {
                if ((CRC & 0x1) != 0) {
                    CRC >>= 1;
                    CRC ^= Polynomial;
                } else {
                    CRC >>= 1;
                }
            }
        }
        return CRC;
    }

    private IDataRecvListener onDataRecvListener = null;

    public interface IDataRecvListener {
        void onDataReceive(String path, byte[] buffer);
    }

    public void setOnDataReceiveListener(IDataRecvListener dataRecvListener) {
        onDataRecvListener = dataRecvListener;
    }
}
